package cn.kone.blog.service.impl;


import cn.kone.blog.domain.ArticleType;
import cn.kone.blog.domain.query.ArticleTypeQuery;
import cn.kone.blog.dto.ArticleTypeDTO;
import cn.kone.blog.mapper.ArticleTypeMapper;
import cn.kone.blog.service.IArticleTypeService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
@CacheConfig(cacheNames = "articleTypeList")
public class ArticleTypeServiceImpl implements IArticleTypeService {
    @Autowired
    private ArticleTypeMapper articleTypeMapper;

//    @Autowired
//    private RedisTemplate redisTemplate;

    //查询单个
    @Override
    public ArticleType findOne(Long id) {
        return articleTypeMapper.findOne(id);
    }

    //查询全部
    @Override
    @Cacheable(key = "'findAll'") //用SpringCache新增缓存,缓存当前方法的返回值
    public List<ArticleType> findAll() {

        return articleTypeMapper.findAll();

//        Object articleTypeList = redisTemplate.opsForValue().get("articleTypeList");
//        //缓存没有就从数据库中查
//        if (articleTypeList == null) {
//            List<ArticleType> list = articleTypeMapper.findAll();
//            //缓存到Redis中
//            redisTemplate.opsForValue().set("articleTypeList", list);
//            return list;
//        }
//        //不等于null就强转类型
//        return (List<ArticleType>) articleTypeList;
    }

    //新增
    @Override
    @Transactional
    @CacheEvict(key = "'addArticleType'") //在增删改的时候需要删除缓存
    public void addArticleType(ArticleType articleType) {

        articleTypeMapper.addArticleType(articleType);


//        try {
//            //增删改以后,如果直接在查询redis中的缓存数据的话会导致数据不一致
//            //保证MySQL中的数据和redis中的数据一致性就需要使用到延时双删
//            //这是第一次删除
//            redisTemplate.delete("articleTypeList");
//            articleTypeMapper.addArticleType(articleType);
//            //先睡眠一秒
//            Thread.sleep(1000);
//            //再执行第二次删除
//            redisTemplate.delete("articleTypeList");
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
    }

    //修改
    @Override
    @Transactional
    @CacheEvict(key = "'updateArticleType'")//在增删改的时候需要删除缓存
    public void updateArticleType(ArticleType articleType) {
        articleTypeMapper.updateArticleType(articleType);
    }


    //删除
    @Override
    @Transactional
    @CacheEvict(key = "'deleteArticleType'")//在增删改的时候需要删除缓存
    public void deleteArticleType(Long id) {
        articleTypeMapper.deleteArticleType(id);
    }

    //分页+高级查询
    @Override
    public List<ArticleType> pageQuery(ArticleTypeQuery articleTypeQuery) {
        PageHelper.startPage(articleTypeQuery.getCurrentPage(), articleTypeQuery.getPageSize());
        return articleTypeMapper.pageQuery(articleTypeQuery);
    }

    //批量删除
    @Override
    @Transactional
    @CacheEvict(key = "'batchDeleteArticleType'")//在增删改的时候需要删除缓存
    public void batchDeleteArticleType(Long[] ids) {
        articleTypeMapper.batchDeleteArticleType(ids);
    }


    //查询类型树
    @Override
    public List<ArticleType> typeTree(Long id,List<ArticleType> list) {
        //先查询出全部的类型

        //将这个转换为map
        Map<Long, ArticleType> map = list.stream().collect(Collectors.toMap(ArticleType::getId, a -> a));
        //定义返回的父类型树,里面是一级类型,子类型都在children集合中
        List<ArticleType> typeTree = new ArrayList<>();
        for (ArticleType type : list) {
            //排除自己的id
            if (type.getId().equals(id)) continue;
            //如果父类型的id为null那么就是一级类型
            if (type.getParentId() == null) {
                typeTree.add(type); //将这个子类型存进这父类型集合里面
            } else {
                ArticleType parent = map.get(type.getParentId());
                parent.getChildren().add(type);
            }
        }
        //返回父类型树
        return typeTree;
    }

    /**
     * 文章类型
     * 文章类型统计
     * 文章类型id
     * @return
     */
    @Override
    public List<ArticleTypeDTO> articleTypeStatistics() {
        return articleTypeMapper.articleTypeStatistics();
    }
}
